/**
 * Copyright (C) 2010 Cloudfarming <info@cloudfarming.nl>
 *
 * Licensed under the Eclipse Public License - v 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.eclipse.org/legal/epl-v10.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package nl.cloudfarming.client.model;

import java.io.Serializable;
import java.util.Date;
import javax.jdo.annotations.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

/**
 * A task is an action that can be done on a field. for example watering a field.
 * @author Merijn Zengers
 */
@NamedQueries(value = {
    @NamedQuery(name = Task.Q_FIND_ALL_TASKS, query = "select t from Task t"),
    @NamedQuery(name = Task.Q_FIND_TASK_BY_PRODUCTION_UNIT_ID, query = "select t from Task t, ProductionUnit pu, Operation o where t.operation = o and o.productionUnit =  pu and pu.id = :id")
                                                               
})
@Entity
@Table(name = "TASK")
public class Task extends Bean implements Serializable, Persistable{
    
    public static final String Q_FIND_ALL_TASKS = "findAllTasks";
    public static final String Q_FIND_TASK_BY_PRODUCTION_UNIT_ID = "findTaskByProductionUnitId";
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    private long id;

    @Column(name = "STARTDATE")
    @Temporal(TemporalType.DATE)
    private Date startDate;

    @Column(name = "ENDDATE")
    @Temporal(TemporalType.DATE)
    private Date endDate;
    
    @Column(name = "PLANDDATE")
    @Temporal(TemporalType.DATE)
    private Date planDate;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "OPERATION_ID")
    private Operation operation;
    
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "PART_FIELD_ID")
    private PartField partField;

    public long getId() {
        return id;
    }

    public Date getEndDate() {
        return endDate;
    }

    public void setEndDate(Date endDate) {
        Date old = this.endDate;
        this.endDate = endDate;
        getPropertyChangeSupport().firePropertyChange("endDate", old, endDate);
        
    }

    public Operation getOperation() {
        return operation;
    }

    public void setOperation(Operation operation) {
        Operation old = this.operation;
        this.operation = operation;
        getPropertyChangeSupport().firePropertyChange("operation", old, operation);
       
    }

    public Date getStartDate() {
        return startDate;
    }

    public void setStartDate(Date startDate) {
        Date old = this.startDate;
        this.startDate = startDate;
        getPropertyChangeSupport().firePropertyChange("startDate", old, startDate);       
    }

    public Date getPlanDate() {
        return planDate;
    }

    public void setPlanDate(Date planDate) {
        Date old = this.planDate;
        this.planDate = planDate;
        getPropertyChangeSupport().firePropertyChange("planDate", old, planDate);
    }

    public PartField getPartField() {
        return partField;
    }

    public void setPartField(PartField partField) {
        PartField old = this.partField; 
        this.partField = partField;
        getPropertyChangeSupport().firePropertyChange("task", old, partField);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Task other = (Task) obj;
        if (this.id != other.id) {
            return false;
        }
        if (this.startDate != other.startDate && (this.startDate == null || !this.startDate.equals(other.startDate))) {
            return false;
        }
        if (this.endDate != other.endDate && (this.endDate == null || !this.endDate.equals(other.endDate))) {
            return false;
        }
        if (this.planDate != other.planDate && (this.planDate == null || !this.planDate.equals(other.planDate))) {
            return false;
        }
        if (this.operation != other.operation && (this.operation == null || !this.operation.equals(other.operation))) {
            return false;
        }
        if (this.partField != other.partField && (this.partField == null || !this.partField.equals(other.partField))) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 97 * hash + (int) (this.id ^ (this.id >>> 32));
        hash = 97 * hash + (this.startDate != null ? this.startDate.hashCode() : 0);
        hash = 97 * hash + (this.endDate != null ? this.endDate.hashCode() : 0);
        hash = 97 * hash + (this.planDate != null ? this.planDate.hashCode() : 0);
        hash = 97 * hash + (this.operation != null ? this.operation.hashCode() : 0);
        hash = 97 * hash + (this.partField != null ? this.partField.hashCode() : 0);
        return hash;
    }

    
    
    /**
     * Task builder class
     *
     * usage: Task task = new Task.Builder().setName("someName").build();
     *
     */
    public static class Builder {

        private Task task;

        public Builder() {
            task = new Task();
        }

        public Builder setStartDate(Date startDate) {
            task.setStartDate(startDate);
            return this;
        }

        public Builder setEndDate(Date endDate) {
            task.setEndDate(endDate);
            return this;
        }

        public Builder setPlanDate(Date planDate) {
            task.setPlanDate(planDate);
            return this;
        }

        public Builder setOperation(Operation operation) {
            task.operation = operation;
            return this;
        }

        public Builder setPartField(PartField partField) {
            task.setPartField(partField);
            return this;
        }

        public Task build() {
            return task;
        }
    }

    
}
